package com.heima.article.service.impl;

import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApHotArticles;
import com.heima.article.mapper.ApHotArticlesMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ApHotArticlesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.util.JsonUtils;
import com.heima.model.article.dtos.ArticleBehaviorStreamMsg;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * <p>
 * 热文章表 服务实现类
 * </p>
 *
 * @author HM
 * @since 2023-05-25
 */
@Service
public class ApHotArticlesServiceImpl extends ServiceImpl<ApHotArticlesMapper, ApHotArticles> implements ApHotArticlesService {
    public static final String PREFIX = "leadnews:hotArticles";
    @Autowired
    private ApArticleService articleService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void updateArticleScore(ArticleBehaviorStreamMsg msg) {
        //更新redis中zset的分值
        double score = calcArticleScore(msg);
        redisTemplate.boundZSetOps(PREFIX).incrementScore(""+msg.getArticleId(),score);
        // 把行为的详数据记录到redis中，将来凌晨使用定任务把详细数据写入到mysq
        //先记录一个要同步所以的article的Id列表,为了将来做定时任务数据更新的时候,避免全库扫描redis
        redisTemplate.boundSetOps(PREFIX+":set").add(""+msg.getArticleId());

        BoundValueOperations<String, String> stringOpt = redisTemplate.boundValueOps(PREFIX+":behavior:" + msg.getArticleId());
        String oldDate= stringOpt.get();
        if (StringUtils.isEmpty(oldDate)){
            stringOpt.set(JsonUtils.toString(msg));
        }else {
            String data=sum(oldDate,msg);
            stringOpt.set(JsonUtils.toString(data));
        }
        // 到来凌晨，定时任务，读取Leadnews:hot_article:set中的所有的articleId
        // 历每一个articleId，读取”Leadnews:hot_article:”+ articleId，这里面就有行为的详细数据




    }



    @Override
    public void calcArticleScore() {
        //1 查询最近5天发布的文章,请改成分页,可以使用分片任务
        List<ApArticle> articleList=articleService.findLatestArticleIn(5);

        //2 计算文章的热度
        if (CollectionUtils.isEmpty(articleList)){
            log.error("五天之内一个文章都查不到");
            return;
        }

        for (ApArticle article : articleList) {
            double score = calcArticleScore(article);
            //3 把热度写入redis的zset
            redisTemplate.boundZSetOps(PREFIX).add(""+article.getId(),score);
            // 当article上下架的时候，redis中需要同步做上下架，接收消息，同步上下架就可以 TODO
            redisTemplate.boundValueOps(PREFIX+":"+article.getId()).set(JsonUtils.toString(article));
        }

    }

    private double calcArticleScore(ArticleBehaviorStreamMsg msg) {
        ApArticle article = new ApArticle();
        article.setViews(Long.parseLong(msg.getViews()==null ?"0":msg.getViews().toString()));
        article.setLikes(Long.parseLong(msg.getLikes()==null ?"0":msg.getLikes().toString()));
        article.setCollection(Long.parseLong(msg.getCollection()==null ?"0":msg.getCollection().toString()));
        article.setComments(Long.parseLong(msg.getComment()==null ?"0":msg.getComment().toString()));
        return calcArticleScore(article);
    }


    private double calcArticleScore(ApArticle article){
        double score=0;
        Long views=article.getViews();
        Long likes=article.getLikes();
        Long comments=article.getComments();
        Long collection=article.getCollection();
        score += views;
        score += 3*likes;
        score += 5*comments;
        score += 8*collection;
        return score;
    }

    public String sum(String oldDate,ArticleBehaviorStreamMsg msg){
        ArticleBehaviorStreamMsg oldMsg = JsonUtils.toBean(oldDate, ArticleBehaviorStreamMsg.class);
        ArticleBehaviorStreamMsg newMsg = new ArticleBehaviorStreamMsg();
        newMsg.setArticleId(msg.getArticleId());
        newMsg.setViews(add(oldMsg.getViews(),msg.getViews()));
        newMsg.setLikes(add(oldMsg.getLikes(),msg.getLikes()));
        newMsg.setComment(add(oldMsg.getComment(),msg.getComment()));
        newMsg.setCollection(add(oldMsg.getCollection(),msg.getCollection()));
        return JsonUtils.toString(newMsg);

    }

    private Integer add(Integer a,Integer b) {
        if (a == null) {
            a = 0;
        }
        if (b == null) {
            b = 0;
        }

        return a + b;

    }



}